/*
 *
 *  * Copyright (c) iwindplus Technologies Co., Ltd.2024-2030, All rights reserved.
 *
 *
 */

package com.iwindplus.base.redis.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.iwindplus.base.domain.constant.CommonConstant.SymbolConstant;
import com.iwindplus.base.redis.service.RedisKeyResolver;
import com.iwindplus.base.util.ExpressionUtil;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.cache.interceptor.KeyGenerator;

/**
 * Redis Key解析器接口实现类（默认）.
 *
 * @author zengdegui
 * @since 2020/6/13
 */
public class DefaultRedisKeyResolver implements RedisKeyResolver {

    @Override
    public String resolver(JoinPoint joinPoint, KeyGenerator keyGenerator, String[] keys) {
        return this.getKeyGeneratorStr(joinPoint, keyGenerator, keys, null);
    }

    /**
     * 获取Redis Key
     *
     * @param joinPoint    切点
     * @param keyGenerator key生成器
     * @param keys         key数组
     * @param prefix       前缀
     * @return String
     */
    protected String getKeyGeneratorStr(JoinPoint joinPoint, KeyGenerator keyGenerator, String[] keys, String prefix) {
        String str = null;
        Object target = joinPoint.getTarget();
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Object[] args = joinPoint.getArgs();
        if (ArrayUtil.isNotEmpty(args) && ArrayUtil.isNotEmpty(keys)) {
            final List<Object> resultList = ExpressionUtil.parse(method, args, keys, Object.class);
            if (CollUtil.isNotEmpty(resultList)) {
                str = resultList.stream()
                    .filter(Objects::nonNull)
                    .map(Object::toString)
                    .collect(Collectors.joining(SymbolConstant.UNDERLINE));
            }
        }
        if (ObjectUtil.isEmpty(str)) {
            Object generatedKey = keyGenerator.generate(target, method, args);
            if (ObjectUtil.isNotEmpty(generatedKey)) {
                str = generatedKey.toString();
            }
        }
        if (ObjectUtil.isNotEmpty(prefix)) {
            if (ObjectUtil.isEmpty(str)) {
                return prefix;
            } else {
                return String.join(SymbolConstant.UNDERLINE, prefix, str);
            }
        }

        return str;
    }

}
